    // 在线用户管理文档说明:
    // 管理的是两类用户:
    //     进入游戏大厅的 & 进入游戏房间的
    // 原因:
    //     进入游戏大厅的用户和进入游戏房间的用户才会建立websocket长连接管理:将用户id和对应的客户端websocket长连接关联起来
    // 作用:
    //     当一个用户发送了消息（实时聊天消息/下棋消息），我们可以找到房间中的其他用户，
    //     在在线用户管理模块中，找到这个用户对应的websocket连接，然后将消息发送给指定的用户
    //     1.通过用户ID找到用户连接，进而实现向指定用户的客户端推送消息websocket连接关闭时，会自动在在线用户管理模块中删除自己的信息
    //     2.可以通过判断一个用户是否还在用户管理模块中来确定用户是否在线。

    // class online_manager{
    // private:
    //     // 防止数据不一致的问题
    //     std::mutex _mutex;
    //     // 用于建立游戏(大厅)用户的用户id与通信协连接的关系
    //     std::unordered_map<uint64_t, wsserver_t::connection_ptr> _hall_user;
    //     // 用于建立游戏(房间)用户的用户id与通信协连接的关系
    //     std::unordered_map<uint64_t, wsserver_t::connection_ptr> _room_user;
    // public:
    //     // online_manager(){}

    //     // wobsocket链接建立的时候,才会加入游戏大厅 & 游戏房间在线用户
    //     bool enter_game_hall(uint64_t uid, wsserver_t::connection_ptr &conn);
    //     bool enter_game_root(uint64_t uid, wsserver_t::connection_ptr &conn);
    //     // wobsocket链接断开的时候,才会移除游戏大厅 & 游戏房间在线用户
    //     bool exit_game_hall(uint64_t uid);
    //     bool exit_game_room(uint64_t uid);
    //     // 判断当前指定用户是否在游戏大厅 / 游戏房间
    //     bool is_in_game_hall(uint64_t uid);
    //     bool is_in_game_room(uint64_t uid);
    //     // 通过用户id在游戏大厅 / 游戏房间用户管理中获取对应的通信连接
    //     wsserver_t::connection_ptr get_conn_from_hall(uint64_t uid);
    //     wsserver_t::connection_ptr get_conn_from_room(uint64_t uid);
    // };



#ifndef __M_ONLINE_H__
#define __M_ONLINE_H__
#include <mutex>
#include <unordered_map>
#include "util.hpp"


// typedef websocketpp::server<websocketpp::config::asio> wsserver_t;

class online_manager{
private:
    // 防止数据不一致的问题
    std::mutex _mutex;
    // 用于建立游戏(大厅)用户的用户id与通信协连接的关系
    std::unordered_map<uint64_t, wsserver_t::connection_ptr> _hall_user;
    // 用于建立游戏(房间)用户的用户id与通信协连接的关系
    std::unordered_map<uint64_t, wsserver_t::connection_ptr> _room_user;
public:
    online_manager(){}

    // wobsocket链接建立的时候,才会加入游戏大厅 & 游戏房间在线用户
    bool enter_game_hall(uint64_t uid, wsserver_t::connection_ptr &conn){
        std::unique_lock<std::mutex> lock(_mutex);    // 得防止数据不一致的问题
        _hall_user.insert(std::make_pair(uid, conn)); // 调用 unordered_map 的成员函数 insert 函数
    }
    bool enter_game_room(uint64_t uid, wsserver_t::connection_ptr &conn){
        std::unique_lock<std::mutex> lock(_mutex);
        _room_user.insert(std::make_pair(uid, conn));
    }

    // wobsocket链接断开的时候,才会移除游戏大厅 & 游戏房间在线用户
    bool exit_game_hall(uint64_t uid){
        std::unique_lock<std::mutex> lock(_mutex);
        _hall_user.erase(uid);
    }
    bool exit_game_room(uint64_t uid){
        std::unique_lock<std::mutex> lock(_mutex);
        _room_user.erase(uid);
    }

    // 判断当前指定用户是否在游戏大厅 / 游戏房间
    bool is_in_game_hall(uint64_t uid){
        std::unique_lock<std::mutex> lock(_mutex);
        auto it = _hall_user.find(uid);
        if(it == _hall_user.end())
            return false;

        return true;
    }
    bool is_in_game_room(uint64_t uid){
        std::unique_lock<std::mutex> lock(_mutex);
        auto it = _room_user.find(uid);
        if(it == _room_user.end())
            return false;

        return true;
    }

    // 通过用户id在游戏大厅 / 游戏房间用户管理中获取对应的通信连接
    wsserver_t::connection_ptr get_conn_from_hall(uint64_t uid){
        std::unique_lock<std::mutex> lock(_mutex);
        auto it = _hall_user.find(uid);
        if(it == _hall_user.end())
            return wsserver_t::connection_ptr();

        return it->second; 
    }
    wsserver_t::connection_ptr get_conn_from_room(uint64_t uid){
        std::unique_lock<std::mutex> lock(_mutex);
        auto it = _room_user.find(uid);
        if(it == _room_user.end())
            return wsserver_t::connection_ptr();

        return it->second;  // std::unordered_map<uint64_t, wsserver_t::connection_ptr>
    }
};



#endif

